/*
 * @Author: Hp_lucky 1063512385@qq.com
 * @Date: 2024-08-28 11:36:48
 * @LastEditors: Hp_lucky 1063512385@qq.com
 * @LastEditTime: 2024-10-23 19:36:11
 * @FilePath: \cocos_frame\assets\script\src\Basic\Manager\EventManager.ts
 */
import { Singleton } from './BaseManager';

interface EventHandler {
  handler: (...args: unknown[]) => void;
  target: unknown;
  times: number;
}

export class EventManager extends Singleton {
  className: string = 'EventManager';
  private _handlers: Map<string, EventHandler[]> = new Map<string, EventHandler[]>();

  /**
   * 发送指定事件的广播
   * @param event 事件类型
   * @param args 传递给Handler的参数
   */
  emit(event: string, ...args: unknown[]) {
    const handlers = this._handlers.get(event);
    if (handlers == null || handlers.length <= 0) return;
    const newHandlers = [];
    const length = handlers.length;
    const tempHandlers = [...handlers];
    for (let i = 0; i < length; i++) {
      const element = tempHandlers.shift();
      if (element == null) continue;
      if (element.times > 0) {
        element.times--;
      }
      element.handler.call(element.target, ...args);
      if (element.times !== 0) {
        newHandlers.push(element);
      }
    }
    this._handlers.set(event, newHandlers);
    // LogUtil.i('EventManager', 'ReceivedEvent: ', event, handlers);
  }

  /**
   * 发送指定事件的广播，并在Handler执行后删除它们的监听
   * @param event 事件类型
   * @param args 传递给Handler的参数
   */
  emitAndShift(event: string, ...args: unknown[]) {
    const handlers = this._handlers[event];
    if (handlers == null || handlers.length <= 0) return;
    const length = handlers.length;
    for (let i = 0; i < length; i++) {
      const handler = handlers.shift();
      handler.handler(...args);
    }
    // LogUtil.i('EventManager', 'ReceivedEventAndShift: ', event, handlers);
  }

  /**
   * 获取指定事件类型的所有Handler
   * @param event 事件类型
   * @returns 这类事件的所有Handler数组的引用
   */
  get(event: string) {
    return this._handlers[event];
  }

  /**
   * 注册指定事件的Handler
   * @param event 事件类型
   * @param handler 对应的Handler
   */
  register(event: string, handler: (...args: unknown[]) => void, target: unknown, times: number = -1) {
    let handlers: EventHandler[];
    if (!this._handlers.has(event)) {
      handlers = [];
      this._handlers.set(event, handlers);
    } else {
      handlers = this._handlers.get(event);
      for (let i = 0; i < handlers.length; i++) {
        if (handlers[i].handler === handler) {
          return;
        }
      }
    }
    handlers.push({ handler: handler, target: target, times: times });
  }

  /**
   * 取消注册某个Handler，可以在emit()期间调用，但此次emit()调用期间不会生效
   * @param event 事件类型
   * @param handler 对应的Handler
   */
  unregister(event: string, handler: (...args: unknown[]) => void) {
    const handlers = this._handlers.get(event);
    if (handlers == null || handlers.length <= 0) return;
    const len = handlers.length;
    for (let i = 0; i < len; i++) {
      const element = handlers[i];
      if (element.handler === handler) {
        handlers.splice(i, 1);
        break;
      }
    }
  }
}
